package at.fhooe.ems.service;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import at.fhooe.ems.dal.ClientRequestModel;
import at.fhooe.ems.dal.ClientResponseModel;
import at.fhooe.ems.dal.Persistence;
import at.fhooe.ems.dal.SensorDataModel;
import at.fhooe.ems.util.DataUtil;

public class Server{

	private static final int PORT = 9999;
	private ServerSocket listener;
	private static ArrayList<Socket> clients = new ArrayList<Socket>();
	
	public Server(AdapterDataRecipient dataRecipient){
		try {
			listener = new ServerSocket(PORT);
			
			while(true){
				System.out.println("Server: Initialize");
				Socket socket = listener.accept();
				ServerThread st = new ServerThread(socket);
				dataRecipient.setServerThread(st);
				st.run();
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	public static ArrayList<Socket> getClients(){
		return clients;
	}
	
	public static void addClient(Socket s){
		clients.add(s);
	}
}

class ServerThread implements Runnable{
	private static PrintWriter out;
	private static BufferedReader in;
	
	
	public ServerThread(Socket socket){
		try {
			Server.addClient(socket);
			System.out.println("Server: Client added.");
		} catch (Exception e) {
			e.printStackTrace();
		}
		
	}
	
	/**
	 * Receives message from clients.
	 *
	 * @throws IOException Signals that an I/O exception has occurred.
	 */
	void receiveMessage() throws IOException{
		for(Socket socket : Server.getClients()){
			// 1. Receive Client's request in format 'dataFrom*dateTo*type'
			in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
			System.out.println("Server: Msg from client...");
			// 2. Parse CSV request, query for data, generate JSON
			String csvRequest;
			
			if((csvRequest=in.readLine())!=null){
				ClientRequestModel crm = DataUtil.convertCSVToRequestModel(csvRequest);
				SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
				Date fromDate = new Date();
				Date toDate = new Date();
				try {
					fromDate = sdf.parse(crm.getDateFrom());
					toDate = sdf.parse(crm.getDateTo());
				} catch (ParseException e) {
					e.printStackTrace();
				}
				if(fromDate.after(toDate)) break;
				
				ArrayList<ClientResponseModel> response = new Persistence().getSensorDataForTimePeriod(crm);
				String jsonResponse = DataUtil.convertResponseToJson(response);
				
				/*out = new PrintWriter(socket.getOutputStream(), true);
				System.out.println("ServerThread: "+jsonResponse);
				out.println(jsonResponse);*/
				sendMessage(jsonResponse, null);
				
			}
			
		}
	}

	/**
	 * Sends JSON messages to clients.
	 *
	 * @param _jsonMessage the _json message
	 * @throws IOException Signals that an I/O exception has occurred.
	 */
	synchronized void sendMessage(String _jsonMessage, List<String> activeSensors) throws IOException{ 
		Socket s;
		
		for(Socket socket : Server.getClients()){
			s = socket;
			// 1. Send data to Client
			out = new PrintWriter(s.getOutputStream(), true);
			System.out.println("ServerThread: "+_jsonMessage);
			out.println(_jsonMessage);
			if(!_jsonMessage.contains("clientresponse")){
				// 2. Insert into DB
				SensorDataModel sdm = new SensorDataModel();
				sdm = DataUtil.convertJSONtoSensorModel(_jsonMessage);
				int insertedRowsNum = new Persistence().insertSensorData(sdm,activeSensors);
				System.out.println("Server: DB - Inserted "+insertedRowsNum+" row(s).");
			}
		}
	}
	
	public void run(){
		try {
			while(true){
				receiveMessage();
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
		
	}
	
}
